{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The collaborative filter approach focuses on finding users who have given similar ratings to the same books, thus creating a link between users, to whom will be suggested books that were reviewed in a positive way. In this way, we look for associations between users, not between books."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "import tensorflow as tf\n",
    "from sklearn.preprocessing import MinMaxScaler"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "b'Skipping line 6452: expected 8 fields, saw 9\\nSkipping line 43667: expected 8 fields, saw 10\\nSkipping line 51751: expected 8 fields, saw 9\\n'\n",
      "b'Skipping line 92038: expected 8 fields, saw 9\\nSkipping line 104319: expected 8 fields, saw 9\\nSkipping line 121768: expected 8 fields, saw 9\\n'\n",
      "b'Skipping line 144058: expected 8 fields, saw 9\\nSkipping line 150789: expected 8 fields, saw 9\\nSkipping line 157128: expected 8 fields, saw 9\\nSkipping line 180189: expected 8 fields, saw 9\\nSkipping line 185738: expected 8 fields, saw 9\\n'\n",
      "b'Skipping line 209388: expected 8 fields, saw 9\\nSkipping line 220626: expected 8 fields, saw 9\\nSkipping line 227933: expected 8 fields, saw 11\\nSkipping line 228957: expected 8 fields, saw 10\\nSkipping line 245933: expected 8 fields, saw 9\\nSkipping line 251296: expected 8 fields, saw 9\\nSkipping line 259941: expected 8 fields, saw 9\\nSkipping line 261529: expected 8 fields, saw 9\\n'\n",
      "/opt/tljh/user/lib/python3.6/site-packages/IPython/core/interactiveshell.py:3049: DtypeWarning: Columns (3) have mixed types. Specify dtype option on import or set low_memory=False.\n",
      "  interactivity=interactivity, compiler=compiler, result=result)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>User-ID</th>\n",
       "      <th>ISBN</th>\n",
       "      <th>Book-Rating</th>\n",
       "      <th>Book-Title</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td>0</td>\n",
       "      <td>276725</td>\n",
       "      <td>034545104X</td>\n",
       "      <td>0</td>\n",
       "      <td>Flesh Tones: A Novel</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>1</td>\n",
       "      <td>2313</td>\n",
       "      <td>034545104X</td>\n",
       "      <td>5</td>\n",
       "      <td>Flesh Tones: A Novel</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>2</td>\n",
       "      <td>6543</td>\n",
       "      <td>034545104X</td>\n",
       "      <td>0</td>\n",
       "      <td>Flesh Tones: A Novel</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>3</td>\n",
       "      <td>8680</td>\n",
       "      <td>034545104X</td>\n",
       "      <td>5</td>\n",
       "      <td>Flesh Tones: A Novel</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>4</td>\n",
       "      <td>10314</td>\n",
       "      <td>034545104X</td>\n",
       "      <td>9</td>\n",
       "      <td>Flesh Tones: A Novel</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   User-ID        ISBN  Book-Rating            Book-Title\n",
       "0   276725  034545104X            0  Flesh Tones: A Novel\n",
       "1     2313  034545104X            5  Flesh Tones: A Novel\n",
       "2     6543  034545104X            0  Flesh Tones: A Novel\n",
       "3     8680  034545104X            5  Flesh Tones: A Novel\n",
       "4    10314  034545104X            9  Flesh Tones: A Novel"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "rating = pd.read_csv('data/BX-Book-Ratings.csv', sep=';', error_bad_lines=False, encoding=\"latin-1\")\n",
    "user = pd.read_csv('data/BX-Users.csv', sep=';', error_bad_lines=False, encoding=\"latin-1\")\n",
    "book = pd.read_csv('data/BX-Books.csv', sep=';', error_bad_lines=False, encoding=\"latin-1\")\n",
    "book_rating = pd.merge(rating, book, on='ISBN')\n",
    "cols = ['Year-Of-Publication', 'Publisher', 'Book-Author', 'Image-URL-S', 'Image-URL-M', 'Image-URL-L']\n",
    "book_rating.drop(cols, axis=1, inplace=True)\n",
    "book_rating.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>User-ID</th>\n",
       "      <th>ISBN</th>\n",
       "      <th>Book-Rating</th>\n",
       "      <th>Book-Title</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td>0</td>\n",
       "      <td>276725</td>\n",
       "      <td>034545104X</td>\n",
       "      <td>0</td>\n",
       "      <td>Flesh Tones: A Novel</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>1</td>\n",
       "      <td>2313</td>\n",
       "      <td>034545104X</td>\n",
       "      <td>5</td>\n",
       "      <td>Flesh Tones: A Novel</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>2</td>\n",
       "      <td>6543</td>\n",
       "      <td>034545104X</td>\n",
       "      <td>0</td>\n",
       "      <td>Flesh Tones: A Novel</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   User-ID        ISBN  Book-Rating            Book-Title\n",
       "0   276725  034545104X            0  Flesh Tones: A Novel\n",
       "1     2313  034545104X            5  Flesh Tones: A Novel\n",
       "2     6543  034545104X            0  Flesh Tones: A Novel"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "book_rating.head(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Book-Title</th>\n",
       "      <th>RatingCount_book</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td>0</td>\n",
       "      <td>A Light in the Storm: The Civil War Diary of ...</td>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>1</td>\n",
       "      <td>Always Have Popsicles</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>2</td>\n",
       "      <td>Apple Magic (The Collector's series)</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>3</td>\n",
       "      <td>Ask Lily (Young Women of Faith: Lily Series, ...</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>4</td>\n",
       "      <td>Beyond IBM: Leadership Marketing and Finance ...</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                          Book-Title  RatingCount_book\n",
       "0   A Light in the Storm: The Civil War Diary of ...                 4\n",
       "1                              Always Have Popsicles                 1\n",
       "2               Apple Magic (The Collector's series)                 1\n",
       "3   Ask Lily (Young Women of Faith: Lily Series, ...                 1\n",
       "4   Beyond IBM: Leadership Marketing and Finance ...                 1"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "rating_count = (book_rating.\n",
    "     groupby(by = ['Book-Title'])['Book-Rating'].\n",
    "     count().\n",
    "     reset_index().\n",
    "     rename(columns = {'Book-Rating': 'RatingCount_book'})\n",
    "     [['Book-Title', 'RatingCount_book']]\n",
    "    )\n",
    "rating_count.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Book-Title</th>\n",
       "      <th>RatingCount_book</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td>75</td>\n",
       "      <td>'Salem's Lot</td>\n",
       "      <td>47</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>203</td>\n",
       "      <td>10 Lb. Penalty</td>\n",
       "      <td>61</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>422</td>\n",
       "      <td>101 Dalmatians</td>\n",
       "      <td>37</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>673</td>\n",
       "      <td>14,000 Things to Be Happy About</td>\n",
       "      <td>28</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>697</td>\n",
       "      <td>16 Lighthouse Road</td>\n",
       "      <td>65</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                          Book-Title  RatingCount_book\n",
       "75                      'Salem's Lot                47\n",
       "203                   10 Lb. Penalty                61\n",
       "422                   101 Dalmatians                37\n",
       "673  14,000 Things to Be Happy About                28\n",
       "697               16 Lighthouse Road                65"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "threshold = 25\n",
    "rating_count = rating_count.query('RatingCount_book >= @threshold')\n",
    "rating_count.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>User-ID</th>\n",
       "      <th>ISBN</th>\n",
       "      <th>Book-Rating</th>\n",
       "      <th>Book-Title</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td>0</td>\n",
       "      <td>276725</td>\n",
       "      <td>034545104X</td>\n",
       "      <td>0</td>\n",
       "      <td>Flesh Tones: A Novel</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>1</td>\n",
       "      <td>2313</td>\n",
       "      <td>034545104X</td>\n",
       "      <td>5</td>\n",
       "      <td>Flesh Tones: A Novel</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>2</td>\n",
       "      <td>6543</td>\n",
       "      <td>034545104X</td>\n",
       "      <td>0</td>\n",
       "      <td>Flesh Tones: A Novel</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   User-ID        ISBN  Book-Rating            Book-Title\n",
       "0   276725  034545104X            0  Flesh Tones: A Novel\n",
       "1     2313  034545104X            5  Flesh Tones: A Novel\n",
       "2     6543  034545104X            0  Flesh Tones: A Novel"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "book_rating.head(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "user_rating = pd.merge(rating_count, book_rating, left_on='Book-Title', right_on='Book-Title', how='left')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Book-Title</th>\n",
       "      <th>RatingCount_book</th>\n",
       "      <th>User-ID</th>\n",
       "      <th>ISBN</th>\n",
       "      <th>Book-Rating</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td>0</td>\n",
       "      <td>'Salem's Lot</td>\n",
       "      <td>47</td>\n",
       "      <td>8936</td>\n",
       "      <td>067103975X</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>1</td>\n",
       "      <td>'Salem's Lot</td>\n",
       "      <td>47</td>\n",
       "      <td>172245</td>\n",
       "      <td>067103975X</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>2</td>\n",
       "      <td>'Salem's Lot</td>\n",
       "      <td>47</td>\n",
       "      <td>189835</td>\n",
       "      <td>067103975X</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     Book-Title  RatingCount_book  User-ID        ISBN  Book-Rating\n",
       "0  'Salem's Lot                47     8936  067103975X            0\n",
       "1  'Salem's Lot                47   172245  067103975X            0\n",
       "2  'Salem's Lot                47   189835  067103975X            5"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "user_rating.head(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>User-ID</th>\n",
       "      <th>RatingCount_user</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td>0</td>\n",
       "      <td>8</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>1</td>\n",
       "      <td>9</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>2</td>\n",
       "      <td>10</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>3</td>\n",
       "      <td>14</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>4</td>\n",
       "      <td>16</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   User-ID  RatingCount_user\n",
       "0        8                 2\n",
       "1        9                 2\n",
       "2       10                 1\n",
       "3       14                 1\n",
       "4       16                 2"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "user_count = (user_rating.\n",
    "     groupby(by = ['User-ID'])['Book-Rating'].\n",
    "     count().\n",
    "     reset_index().\n",
    "     rename(columns = {'Book-Rating': 'RatingCount_user'})\n",
    "     [['User-ID', 'RatingCount_user']]\n",
    "    )\n",
    "user_count.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>User-ID</th>\n",
       "      <th>RatingCount_user</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td>52</td>\n",
       "      <td>243</td>\n",
       "      <td>68</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>54</td>\n",
       "      <td>254</td>\n",
       "      <td>139</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>89</td>\n",
       "      <td>487</td>\n",
       "      <td>21</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>96</td>\n",
       "      <td>507</td>\n",
       "      <td>61</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>115</td>\n",
       "      <td>638</td>\n",
       "      <td>51</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     User-ID  RatingCount_user\n",
       "52       243                68\n",
       "54       254               139\n",
       "89       487                21\n",
       "96       507                61\n",
       "115      638                51"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "threshold = 20\n",
    "user_count = user_count.query('RatingCount_user >= @threshold')\n",
    "user_count.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "combined = user_rating.merge(user_count, left_on = 'User-ID', right_on = 'User-ID', how = 'inner')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Book-Title</th>\n",
       "      <th>RatingCount_book</th>\n",
       "      <th>User-ID</th>\n",
       "      <th>ISBN</th>\n",
       "      <th>Book-Rating</th>\n",
       "      <th>RatingCount_user</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td>0</td>\n",
       "      <td>'Salem's Lot</td>\n",
       "      <td>47</td>\n",
       "      <td>8936</td>\n",
       "      <td>067103975X</td>\n",
       "      <td>0</td>\n",
       "      <td>177</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>1</td>\n",
       "      <td>1st to Die: A Novel</td>\n",
       "      <td>509</td>\n",
       "      <td>8936</td>\n",
       "      <td>0446610038</td>\n",
       "      <td>0</td>\n",
       "      <td>177</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>2</td>\n",
       "      <td>A Case of Need</td>\n",
       "      <td>236</td>\n",
       "      <td>8936</td>\n",
       "      <td>0451210638</td>\n",
       "      <td>0</td>\n",
       "      <td>177</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "            Book-Title  RatingCount_book  User-ID        ISBN  Book-Rating  \\\n",
       "0         'Salem's Lot                47     8936  067103975X            0   \n",
       "1  1st to Die: A Novel               509     8936  0446610038            0   \n",
       "2       A Case of Need               236     8936  0451210638            0   \n",
       "\n",
       "   RatingCount_user  \n",
       "0               177  \n",
       "1               177  \n",
       "2               177  "
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "combined.head(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(263467, 6)"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "combined.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Number of unique books:  5850\n",
      "Number of unique users:  3192\n"
     ]
    }
   ],
   "source": [
    "print('Number of unique books: ', combined['Book-Title'].nunique())\n",
    "print('Number of unique users: ', combined['User-ID'].nunique())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Normalize the ratings."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "scaler = MinMaxScaler()\n",
    "combined['Book-Rating'] = combined['Book-Rating'].values.astype(float)\n",
    "rating_scaled = pd.DataFrame(scaler.fit_transform(combined['Book-Rating'].values.reshape(-1,1)))\n",
    "combined['Book-Rating'] = rating_scaled"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Abd build the user book matrix."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/opt/tljh/user/lib/python3.6/site-packages/ipykernel_launcher.py:8: FutureWarning: Method .as_matrix will be removed in a future version. Use .values instead.\n",
      "  \n"
     ]
    }
   ],
   "source": [
    "combined = combined.drop_duplicates(['User-ID', 'Book-Title'])\n",
    "user_book_matrix = combined.pivot(index='User-ID', columns='Book-Title', values='Book-Rating')\n",
    "user_book_matrix.fillna(0, inplace=True)\n",
    "\n",
    "users = user_book_matrix.index.tolist()\n",
    "books = user_book_matrix.columns.tolist()\n",
    "\n",
    "user_book_matrix = user_book_matrix.as_matrix()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "tf.placeholder only available in v1, so we have to work around. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING: Logging before flag parsing goes to stderr.\n",
      "W0913 05:27:19.644382 140528474883904 deprecation.py:323] From /opt/tljh/user/lib/python3.6/site-packages/tensorflow_core/python/compat/v2_compat.py:65: disable_resource_variables (from tensorflow.python.ops.variable_scope) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "non-resource variables are not supported in the long term\n"
     ]
    }
   ],
   "source": [
    "import tensorflow.compat.v1 as tf\n",
    "tf.disable_v2_behavior()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We will initialize the TensorFlow placeholder. Then, weights and biases are randomly initialized, the following code are taken from the book: Python Machine Learning Cook Book - Second Edition"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "num_input = combined['Book-Title'].nunique()\n",
    "num_hidden_1 = 10\n",
    "num_hidden_2 = 5\n",
    "\n",
    "X = tf.placeholder(tf.float64, [None, num_input])\n",
    "\n",
    "weights = {\n",
    "    'encoder_h1': tf.Variable(tf.random_normal([num_input, num_hidden_1], dtype=tf.float64)),\n",
    "    'encoder_h2': tf.Variable(tf.random_normal([num_hidden_1, num_hidden_2], dtype=tf.float64)),\n",
    "    'decoder_h1': tf.Variable(tf.random_normal([num_hidden_2, num_hidden_1], dtype=tf.float64)),\n",
    "    'decoder_h2': tf.Variable(tf.random_normal([num_hidden_1, num_input], dtype=tf.float64)),\n",
    "}\n",
    "\n",
    "biases = {\n",
    "    'encoder_b1': tf.Variable(tf.random_normal([num_hidden_1], dtype=tf.float64)),\n",
    "    'encoder_b2': tf.Variable(tf.random_normal([num_hidden_2], dtype=tf.float64)),\n",
    "    'decoder_b1': tf.Variable(tf.random_normal([num_hidden_1], dtype=tf.float64)),\n",
    "    'decoder_b2': tf.Variable(tf.random_normal([num_input], dtype=tf.float64)),\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, we can build the encoder and decoder model, as follows:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "def encoder(x):\n",
    "    layer_1 = tf.nn.sigmoid(tf.add(tf.matmul(x, weights['encoder_h1']), biases['encoder_b1']))\n",
    "    layer_2 = tf.nn.sigmoid(tf.add(tf.matmul(layer_1, weights['encoder_h2']), biases['encoder_b2']))\n",
    "    return layer_2\n",
    "\n",
    "def decoder(x):\n",
    "    layer_1 = tf.nn.sigmoid(tf.add(tf.matmul(x, weights['decoder_h1']), biases['decoder_b1']))\n",
    "    layer_2 = tf.nn.sigmoid(tf.add(tf.matmul(layer_1, weights['decoder_h2']), biases['decoder_b2']))\n",
    "    return layer_2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We will construct the model and the predictions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "encoder_op = encoder(X)\n",
    "decoder_op = decoder(encoder_op)\n",
    "\n",
    "y_pred = decoder_op\n",
    "\n",
    "y_true = X"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "define loss function and optimizer, and minimize the squared error, and define the evaluation metrics"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "W0913 05:27:31.793503 140528474883904 deprecation.py:323] From /opt/tljh/user/lib/python3.6/site-packages/tensorflow_core/python/ops/losses/losses_impl.py:121: where (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Use tf.where in 2.0, which has the same broadcast rule as np.where\n",
      "W0913 05:27:31.950875 140528474883904 deprecation.py:506] From /opt/tljh/user/lib/python3.6/site-packages/tensorflow_core/python/training/rmsprop.py:119: calling Ones.__init__ (from tensorflow.python.ops.init_ops) with dtype is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Call initializer instance with the dtype argument instead of passing it to the constructor\n",
      "W0913 05:27:32.106023 140528474883904 deprecation.py:323] From /opt/tljh/user/lib/python3.6/site-packages/tensorflow_core/python/ops/metrics_impl.py:2026: div (from tensorflow.python.ops.math_ops) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Deprecated in favor of operator or tf.math.divide.\n"
     ]
    }
   ],
   "source": [
    "loss = tf.losses.mean_squared_error(y_true, y_pred)\n",
    "optimizer = tf.train.RMSPropOptimizer(0.03).minimize(loss)\n",
    "eval_x = tf.placeholder(tf.int32, )\n",
    "eval_y = tf.placeholder(tf.int32, )\n",
    "pre, pre_op = tf.metrics.precision(labels=eval_x, predictions=eval_y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Initialize the variables. Because TensorFlow uses computational graphs for its operations, placeholders and variables must be initialized."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "init = tf.global_variables_initializer()\n",
    "local_init = tf.local_variables_initializer()\n",
    "pred_data = pd.DataFrame()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can finally start to train our model.\n",
    "\n",
    "We split training data into batches, and we feed the network with them.\n",
    "\n",
    "We train our model with vectors of user ratings, each vector represents a user and each column a book, and entries are ratings that the user gave to books. \n",
    "\n",
    "After a few trials, I discovered that training model for 5 epochs with a batch size of 10 would be consum enough memory. This means that the entire training set will feed our neural network 20 times, every time using 50 users."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch: 1 Loss: 0.35731346364859695\n",
      "epoch: 2 Loss: 0.29650099804768193\n",
      "epoch: 3 Loss: 0.06677147072668259\n",
      "epoch: 4 Loss: 0.0035869495042569035\n",
      "epoch: 5 Loss: 0.0032511451396743185\n",
      "epoch: 6 Loss: 0.0031387122887811\n",
      "epoch: 7 Loss: 0.002954580835169079\n",
      "epoch: 8 Loss: 0.00292991557296693\n",
      "epoch: 9 Loss: 0.0029140610547204104\n",
      "epoch: 10 Loss: 0.0029028362855519894\n",
      "epoch: 11 Loss: 0.0028944522587602936\n",
      "epoch: 12 Loss: 0.002887899707235232\n",
      "epoch: 13 Loss: 0.0028822272862461243\n",
      "epoch: 14 Loss: 0.002758970858969286\n",
      "epoch: 15 Loss: 0.0027070576939117776\n",
      "epoch: 16 Loss: 0.002704087681914833\n",
      "epoch: 17 Loss: 0.0027016002574812743\n",
      "epoch: 18 Loss: 0.002699464953576143\n",
      "epoch: 19 Loss: 0.0026976102323445317\n",
      "epoch: 20 Loss: 0.002695984468068723\n",
      "epoch: 21 Loss: 0.0026945482100267986\n",
      "epoch: 22 Loss: 0.002693270453364476\n",
      "epoch: 23 Loss: 0.0026921267764499555\n",
      "epoch: 24 Loss: 0.002691097311921172\n",
      "epoch: 25 Loss: 0.0026901662029878617\n",
      "epoch: 26 Loss: 0.002689320242267798\n",
      "epoch: 27 Loss: 0.0026885485404508783\n",
      "epoch: 28 Loss: 0.002687841899447389\n",
      "epoch: 29 Loss: 0.002687192727954915\n",
      "epoch: 30 Loss: 0.0026865942764433695\n",
      "epoch: 31 Loss: 0.002686040959535883\n",
      "epoch: 32 Loss: 0.002685527965825583\n",
      "epoch: 33 Loss: 0.0026850509623597774\n",
      "epoch: 34 Loss: 0.0026846062916504976\n",
      "epoch: 35 Loss: 0.0026841906083563526\n",
      "epoch: 36 Loss: 0.0026838010123286108\n",
      "epoch: 37 Loss: 0.0026834349296372996\n",
      "epoch: 38 Loss: 0.002683090005110908\n",
      "epoch: 39 Loss: 0.002682764225148156\n",
      "epoch: 40 Loss: 0.002682456099377065\n",
      "epoch: 41 Loss: 0.002682164539122483\n",
      "epoch: 42 Loss: 0.0026818890876781484\n",
      "epoch: 43 Loss: 0.0026816298742522744\n",
      "epoch: 44 Loss: 0.0026813868758176545\n",
      "epoch: 45 Loss: 0.002681159273629169\n",
      "epoch: 46 Loss: 0.002680945431475865\n",
      "epoch: 47 Loss: 0.002680743581379999\n",
      "epoch: 48 Loss: 0.002680552151095081\n",
      "epoch: 49 Loss: 0.0026803700864867688\n",
      "epoch: 50 Loss: 0.0026801967773340887\n",
      "epoch: 51 Loss: 0.002680031476532119\n",
      "epoch: 52 Loss: 0.002679873741446779\n",
      "epoch: 53 Loss: 0.0026797230642002364\n",
      "epoch: 54 Loss: 0.0026795790648435824\n",
      "epoch: 55 Loss: 0.002679441281553399\n",
      "epoch: 56 Loss: 0.002679309394507372\n",
      "epoch: 57 Loss: 0.0026791830416666444\n",
      "epoch: 58 Loss: 0.0026790619057674822\n",
      "epoch: 59 Loss: 0.0026789456158160018\n",
      "epoch: 60 Loss: 0.002678833909557907\n",
      "epoch: 61 Loss: 0.002678726540090373\n",
      "epoch: 62 Loss: 0.002678623227249053\n",
      "epoch: 63 Loss: 0.002678523763789089\n",
      "epoch: 64 Loss: 0.002678427971889275\n",
      "epoch: 65 Loss: 0.002678335641746174\n",
      "epoch: 66 Loss: 0.002678246604493604\n",
      "epoch: 67 Loss: 0.0026781606388145258\n",
      "epoch: 68 Loss: 0.0026780776820237657\n",
      "epoch: 69 Loss: 0.0026779975217593077\n",
      "epoch: 70 Loss: 0.002677920014740756\n",
      "epoch: 71 Loss: 0.0026778449984983755\n",
      "epoch: 72 Loss: 0.00267777239883339\n",
      "epoch: 73 Loss: 0.0026777021325919983\n",
      "epoch: 74 Loss: 0.0026776340411423325\n",
      "epoch: 75 Loss: 0.0026775679965554684\n",
      "epoch: 76 Loss: 0.0026775038913711088\n",
      "epoch: 77 Loss: 0.002677441689769154\n",
      "epoch: 78 Loss: 0.0026773812587035225\n",
      "epoch: 79 Loss: 0.002677322575147008\n",
      "epoch: 80 Loss: 0.0026772654433683545\n",
      "epoch: 81 Loss: 0.002677209924773446\n",
      "epoch: 82 Loss: 0.00267715583770321\n",
      "epoch: 83 Loss: 0.002677103147616835\n",
      "epoch: 84 Loss: 0.0026770517982255956\n",
      "epoch: 85 Loss: 0.0026770017728987303\n",
      "epoch: 86 Loss: 0.002676952924517976\n",
      "epoch: 87 Loss: 0.0026769052121460766\n",
      "epoch: 88 Loss: 0.002676858693351048\n",
      "epoch: 89 Loss: 0.002676813254276147\n",
      "epoch: 90 Loss: 0.0026767688552634073\n",
      "epoch: 91 Loss: 0.0026767254911956714\n",
      "epoch: 92 Loss: 0.0026766831467214683\n",
      "epoch: 93 Loss: 0.002676641901156732\n",
      "epoch: 94 Loss: 0.0026766017007713136\n",
      "epoch: 95 Loss: 0.002676562623601857\n",
      "epoch: 96 Loss: 0.002676524696513437\n",
      "epoch: 97 Loss: 0.002676487939974682\n",
      "epoch: 98 Loss: 0.002676452290021129\n",
      "epoch: 99 Loss: 0.002676417825968711\n",
      "epoch: 100 Loss: 0.0026763843955820077\n"
     ]
    }
   ],
   "source": [
    "with tf.Session() as session:\n",
    "    epochs = 100\n",
    "    batch_size = 35\n",
    "\n",
    "    session.run(init)\n",
    "    session.run(local_init)\n",
    "\n",
    "    num_batches = int(user_book_matrix.shape[0] / batch_size)\n",
    "    user_book_matrix = np.array_split(user_book_matrix, num_batches)\n",
    "    \n",
    "    for i in range(epochs):\n",
    "\n",
    "        avg_cost = 0\n",
    "        for batch in user_book_matrix:\n",
    "            _, l = session.run([optimizer, loss], feed_dict={X: batch})\n",
    "            avg_cost += l\n",
    "\n",
    "        avg_cost /= num_batches\n",
    "\n",
    "        print(\"epoch: {} Loss: {}\".format(i + 1, avg_cost))\n",
    "\n",
    "    user_book_matrix = np.concatenate(user_book_matrix, axis=0)\n",
    "\n",
    "    preds = session.run(decoder_op, feed_dict={X: user_book_matrix})\n",
    "\n",
    "    pred_data = pred_data.append(pd.DataFrame(preds))\n",
    "\n",
    "    pred_data = pred_data.stack().reset_index(name='Book-Rating')\n",
    "    pred_data.columns = ['User-ID', 'Book-Title', 'Book-Rating']\n",
    "    pred_data['User-ID'] = pred_data['User-ID'].map(lambda value: users[value])\n",
    "    pred_data['Book-Title'] = pred_data['Book-Title'].map(lambda value: books[value])\n",
    "    \n",
    "    keys = ['User-ID', 'Book-Title']\n",
    "    index_1 = pred_data.set_index(keys).index\n",
    "    index_2 = combined.set_index(keys).index\n",
    "\n",
    "    top_ten_ranked = pred_data[~index_1.isin(index_2)]\n",
    "    top_ten_ranked = top_ten_ranked.sort_values(['User-ID', 'Book-Rating'], ascending=[True, False])\n",
    "    top_ten_ranked = top_ten_ranked.groupby('User-ID').head(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>User-ID</th>\n",
       "      <th>Book-Title</th>\n",
       "      <th>Book-Rating</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td>18660405</td>\n",
       "      <td>278582</td>\n",
       "      <td>The Lovely Bones: A Novel</td>\n",
       "      <td>0.073688</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>18659952</td>\n",
       "      <td>278582</td>\n",
       "      <td>The Da Vinci Code</td>\n",
       "      <td>0.062371</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>18657487</td>\n",
       "      <td>278582</td>\n",
       "      <td>Harry Potter and the Chamber of Secrets (Book 2)</td>\n",
       "      <td>0.046772</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>18660710</td>\n",
       "      <td>278582</td>\n",
       "      <td>The Secret Life of Bees</td>\n",
       "      <td>0.046242</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>18657491</td>\n",
       "      <td>278582</td>\n",
       "      <td>Harry Potter and the Prisoner of Azkaban (Book 3)</td>\n",
       "      <td>0.043700</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>18656352</td>\n",
       "      <td>278582</td>\n",
       "      <td>Bridget Jones's Diary</td>\n",
       "      <td>0.042606</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>18658056</td>\n",
       "      <td>278582</td>\n",
       "      <td>Life of Pi</td>\n",
       "      <td>0.041706</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>18660634</td>\n",
       "      <td>278582</td>\n",
       "      <td>The Red Tent (Bestselling Backlist)</td>\n",
       "      <td>0.038770</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>18657489</td>\n",
       "      <td>278582</td>\n",
       "      <td>Harry Potter and the Goblet of Fire (Book 4)</td>\n",
       "      <td>0.037943</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>18657493</td>\n",
       "      <td>278582</td>\n",
       "      <td>Harry Potter and the Sorcerer's Stone (Harry P...</td>\n",
       "      <td>0.037538</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "          User-ID                                         Book-Title  \\\n",
       "18660405   278582                          The Lovely Bones: A Novel   \n",
       "18659952   278582                                  The Da Vinci Code   \n",
       "18657487   278582   Harry Potter and the Chamber of Secrets (Book 2)   \n",
       "18660710   278582                            The Secret Life of Bees   \n",
       "18657491   278582  Harry Potter and the Prisoner of Azkaban (Book 3)   \n",
       "18656352   278582                              Bridget Jones's Diary   \n",
       "18658056   278582                                         Life of Pi   \n",
       "18660634   278582                The Red Tent (Bestselling Backlist)   \n",
       "18657489   278582       Harry Potter and the Goblet of Fire (Book 4)   \n",
       "18657493   278582  Harry Potter and the Sorcerer's Stone (Harry P...   \n",
       "\n",
       "          Book-Rating  \n",
       "18660405     0.073688  \n",
       "18659952     0.062371  \n",
       "18657487     0.046772  \n",
       "18660710     0.046242  \n",
       "18657491     0.043700  \n",
       "18656352     0.042606  \n",
       "18658056     0.041706  \n",
       "18660634     0.038770  \n",
       "18657489     0.037943  \n",
       "18657493     0.037538  "
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "top_ten_ranked.loc[top_ten_ranked['User-ID'] == 278582]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>User-ID</th>\n",
       "      <th>ISBN</th>\n",
       "      <th>Book-Rating</th>\n",
       "      <th>Book-Title</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td>174885</td>\n",
       "      <td>278582</td>\n",
       "      <td>0226848620</td>\n",
       "      <td>10</td>\n",
       "      <td>Chinese Bell Murders (Judge Dee Mysteries)</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>176582</td>\n",
       "      <td>278582</td>\n",
       "      <td>157566254X</td>\n",
       "      <td>10</td>\n",
       "      <td>Skin Deep, Blood Red</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>40008</td>\n",
       "      <td>278582</td>\n",
       "      <td>0441478123</td>\n",
       "      <td>10</td>\n",
       "      <td>The Left Hand of Darkness (Remembering Tomorrow)</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>174861</td>\n",
       "      <td>278582</td>\n",
       "      <td>0061044725</td>\n",
       "      <td>10</td>\n",
       "      <td>Search the Shadows</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>58156</td>\n",
       "      <td>278582</td>\n",
       "      <td>0451202503</td>\n",
       "      <td>10</td>\n",
       "      <td>The Songcatcher: A Ballad Novel</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>64570</td>\n",
       "      <td>278582</td>\n",
       "      <td>1400034779</td>\n",
       "      <td>10</td>\n",
       "      <td>The No. 1 Ladies' Detective Agency (Today Show...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>175958</td>\n",
       "      <td>278582</td>\n",
       "      <td>0345350499</td>\n",
       "      <td>10</td>\n",
       "      <td>The Mists of Avalon</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>176314</td>\n",
       "      <td>278582</td>\n",
       "      <td>0449223558</td>\n",
       "      <td>9</td>\n",
       "      <td>Murdering Mr. Monti: A Merry Little Tale of Se...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>174877</td>\n",
       "      <td>278582</td>\n",
       "      <td>0140277471</td>\n",
       "      <td>9</td>\n",
       "      <td>Blanche Cleans Up</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>176438</td>\n",
       "      <td>278582</td>\n",
       "      <td>0515136557</td>\n",
       "      <td>8</td>\n",
       "      <td>The Cat Who Brought Down the House</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>176503</td>\n",
       "      <td>278582</td>\n",
       "      <td>0671877445</td>\n",
       "      <td>8</td>\n",
       "      <td>Cetaganda (Bujold, Lois Mcmaster. Vorkosigan A...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>176484</td>\n",
       "      <td>278582</td>\n",
       "      <td>055327239X</td>\n",
       "      <td>8</td>\n",
       "      <td>Service of All the Dead</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>176187</td>\n",
       "      <td>278582</td>\n",
       "      <td>0425191583</td>\n",
       "      <td>8</td>\n",
       "      <td>Imitation in Death (Eve Dallas Mysteries (Pape...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>175949</td>\n",
       "      <td>278582</td>\n",
       "      <td>0345348176</td>\n",
       "      <td>8</td>\n",
       "      <td>From Doon With Death</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>176263</td>\n",
       "      <td>278582</td>\n",
       "      <td>0449003183</td>\n",
       "      <td>8</td>\n",
       "      <td>Brunswick Gardens (Charlotte &amp;amp; Thomas Pitt...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>176290</td>\n",
       "      <td>278582</td>\n",
       "      <td>0449206874</td>\n",
       "      <td>8</td>\n",
       "      <td>One Fine Day the Rabbi Bought a Cross</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>176305</td>\n",
       "      <td>278582</td>\n",
       "      <td>0449217213</td>\n",
       "      <td>8</td>\n",
       "      <td>Incident at Badamya</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>174882</td>\n",
       "      <td>278582</td>\n",
       "      <td>0141001976</td>\n",
       "      <td>8</td>\n",
       "      <td>Blanche Passes Go</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>176584</td>\n",
       "      <td>278582</td>\n",
       "      <td>1890208442</td>\n",
       "      <td>8</td>\n",
       "      <td>Daddy's Gone A-Hunting (Wesley Farrell Novels)</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>176572</td>\n",
       "      <td>278582</td>\n",
       "      <td>0804109818</td>\n",
       "      <td>8</td>\n",
       "      <td>The Jewel That Was Ours</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>23996</td>\n",
       "      <td>278582</td>\n",
       "      <td>0449221512</td>\n",
       "      <td>8</td>\n",
       "      <td>I Is for Innocent</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>60802</td>\n",
       "      <td>278582</td>\n",
       "      <td>0671001795</td>\n",
       "      <td>8</td>\n",
       "      <td>Two for the Dough</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>108791</td>\n",
       "      <td>278582</td>\n",
       "      <td>0345440064</td>\n",
       "      <td>8</td>\n",
       "      <td>Death of a Stranger</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>176517</td>\n",
       "      <td>278582</td>\n",
       "      <td>0743406583</td>\n",
       "      <td>7</td>\n",
       "      <td>Maggody and the Moonbeams</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>174895</td>\n",
       "      <td>278582</td>\n",
       "      <td>0312957785</td>\n",
       "      <td>7</td>\n",
       "      <td>The Venus Throw</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>175303</td>\n",
       "      <td>278582</td>\n",
       "      <td>0312980140</td>\n",
       "      <td>7</td>\n",
       "      <td>Seven Up (A Stephanie Plum Novel)</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>175596</td>\n",
       "      <td>278582</td>\n",
       "      <td>0312983867</td>\n",
       "      <td>7</td>\n",
       "      <td>Hard Eight : A Stephanie Plum Novel (A Stephan...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>176171</td>\n",
       "      <td>278582</td>\n",
       "      <td>0425190927</td>\n",
       "      <td>7</td>\n",
       "      <td>The Wife Test</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>176139</td>\n",
       "      <td>278582</td>\n",
       "      <td>0425163717</td>\n",
       "      <td>7</td>\n",
       "      <td>Holiday in Death</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>176562</td>\n",
       "      <td>278582</td>\n",
       "      <td>0743480562</td>\n",
       "      <td>6</td>\n",
       "      <td>CSI, Miami: Heat Wave</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>176567</td>\n",
       "      <td>278582</td>\n",
       "      <td>0765344513</td>\n",
       "      <td>6</td>\n",
       "      <td>Over the Wine-Dark Sea (Hellenistic Seafaring ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>175905</td>\n",
       "      <td>278582</td>\n",
       "      <td>0312991460</td>\n",
       "      <td>6</td>\n",
       "      <td>To the Nines (A Stephanie Plum Novel)</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>176255</td>\n",
       "      <td>278582</td>\n",
       "      <td>0425193772</td>\n",
       "      <td>5</td>\n",
       "      <td>Indigo Dying</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>175763</td>\n",
       "      <td>278582</td>\n",
       "      <td>0312990456</td>\n",
       "      <td>5</td>\n",
       "      <td>One for the Money (A Stephanie Plum Novel)</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>175506</td>\n",
       "      <td>278582</td>\n",
       "      <td>0312983298</td>\n",
       "      <td>3</td>\n",
       "      <td>Full Speed (Janet Evanovich's Full Series)</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>174867</td>\n",
       "      <td>278582</td>\n",
       "      <td>0061063746</td>\n",
       "      <td>2</td>\n",
       "      <td>Hang Loose</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>176571</td>\n",
       "      <td>278582</td>\n",
       "      <td>076534503X</td>\n",
       "      <td>0</td>\n",
       "      <td>The Gryphon's Skull (Hellenistic Seafaring Adv...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>176389</td>\n",
       "      <td>278582</td>\n",
       "      <td>048627263X</td>\n",
       "      <td>0</td>\n",
       "      <td>Flatland: A Romance of Many Dimensions (Dover ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>176565</td>\n",
       "      <td>278582</td>\n",
       "      <td>0743497988</td>\n",
       "      <td>0</td>\n",
       "      <td>Law and Order Deadline : An Original Law and O...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>176486</td>\n",
       "      <td>278582</td>\n",
       "      <td>0553574027</td>\n",
       "      <td>0</td>\n",
       "      <td>Antarctica</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>176579</td>\n",
       "      <td>278582</td>\n",
       "      <td>1555971792</td>\n",
       "      <td>0</td>\n",
       "      <td>The Body in Four Parts</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>176385</td>\n",
       "      <td>278582</td>\n",
       "      <td>0451208498</td>\n",
       "      <td>0</td>\n",
       "      <td>Thieves' Paradise</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>176524</td>\n",
       "      <td>278582</td>\n",
       "      <td>0743448677</td>\n",
       "      <td>0</td>\n",
       "      <td>Without Pity : Ann Rule's Most Dangerous Killers</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>14574</td>\n",
       "      <td>278582</td>\n",
       "      <td>0312966970</td>\n",
       "      <td>0</td>\n",
       "      <td>Four To Score (A Stephanie Plum Novel)</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>176331</td>\n",
       "      <td>278582</td>\n",
       "      <td>0451205146</td>\n",
       "      <td>0</td>\n",
       "      <td>Black Hawk Down (Movie Tie-in)</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>17190</td>\n",
       "      <td>278582</td>\n",
       "      <td>0553581112</td>\n",
       "      <td>0</td>\n",
       "      <td>Justice Hall: A Mary Russell Novel (Mary Russe...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>175758</td>\n",
       "      <td>278582</td>\n",
       "      <td>0312985649</td>\n",
       "      <td>0</td>\n",
       "      <td>A Grave Denied (A Kate Shugak Novel)</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>175103</td>\n",
       "      <td>278582</td>\n",
       "      <td>0312976275</td>\n",
       "      <td>0</td>\n",
       "      <td>Hot Six : A Stephanie Plum Novel (A Stephanie ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>174902</td>\n",
       "      <td>278582</td>\n",
       "      <td>0312971346</td>\n",
       "      <td>0</td>\n",
       "      <td>High Five (A Stephanie Plum Novel)</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>174891</td>\n",
       "      <td>278582</td>\n",
       "      <td>0312851561</td>\n",
       "      <td>0</td>\n",
       "      <td>The Sword of Samurai Cat (Tor Fantasy)</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>174890</td>\n",
       "      <td>278582</td>\n",
       "      <td>0312168586</td>\n",
       "      <td>0</td>\n",
       "      <td>Great Harry</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>174869</td>\n",
       "      <td>278582</td>\n",
       "      <td>0140250360</td>\n",
       "      <td>0</td>\n",
       "      <td>Blanche Among the Talented Tenth</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>174852</td>\n",
       "      <td>278582</td>\n",
       "      <td>0061032484</td>\n",
       "      <td>0</td>\n",
       "      <td>Children of the Storm</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>174815</td>\n",
       "      <td>278582</td>\n",
       "      <td>0060549270</td>\n",
       "      <td>0</td>\n",
       "      <td>A Greek God at the Ladies' Club (Avon Romance)</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>174814</td>\n",
       "      <td>278582</td>\n",
       "      <td>0060534397</td>\n",
       "      <td>0</td>\n",
       "      <td>All Shall Be Well</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>174809</td>\n",
       "      <td>278582</td>\n",
       "      <td>0060534389</td>\n",
       "      <td>0</td>\n",
       "      <td>A Share in Death</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>116741</td>\n",
       "      <td>278582</td>\n",
       "      <td>0380817152</td>\n",
       "      <td>0</td>\n",
       "      <td>The Golden One : A Novel of Suspense</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>46554</td>\n",
       "      <td>278582</td>\n",
       "      <td>0312966091</td>\n",
       "      <td>0</td>\n",
       "      <td>Three To Get Deadly : A Stephanie Plum Novel (...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>24674</td>\n",
       "      <td>278582</td>\n",
       "      <td>0425175405</td>\n",
       "      <td>0</td>\n",
       "      <td>Black Notice</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>175760</td>\n",
       "      <td>278582</td>\n",
       "      <td>0312986327</td>\n",
       "      <td>0</td>\n",
       "      <td>Out on a Limb (A Claire Malloy Mystery)</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "        User-ID        ISBN  Book-Rating  \\\n",
       "174885   278582  0226848620           10   \n",
       "176582   278582  157566254X           10   \n",
       "40008    278582  0441478123           10   \n",
       "174861   278582  0061044725           10   \n",
       "58156    278582  0451202503           10   \n",
       "64570    278582  1400034779           10   \n",
       "175958   278582  0345350499           10   \n",
       "176314   278582  0449223558            9   \n",
       "174877   278582  0140277471            9   \n",
       "176438   278582  0515136557            8   \n",
       "176503   278582  0671877445            8   \n",
       "176484   278582  055327239X            8   \n",
       "176187   278582  0425191583            8   \n",
       "175949   278582  0345348176            8   \n",
       "176263   278582  0449003183            8   \n",
       "176290   278582  0449206874            8   \n",
       "176305   278582  0449217213            8   \n",
       "174882   278582  0141001976            8   \n",
       "176584   278582  1890208442            8   \n",
       "176572   278582  0804109818            8   \n",
       "23996    278582  0449221512            8   \n",
       "60802    278582  0671001795            8   \n",
       "108791   278582  0345440064            8   \n",
       "176517   278582  0743406583            7   \n",
       "174895   278582  0312957785            7   \n",
       "175303   278582  0312980140            7   \n",
       "175596   278582  0312983867            7   \n",
       "176171   278582  0425190927            7   \n",
       "176139   278582  0425163717            7   \n",
       "176562   278582  0743480562            6   \n",
       "176567   278582  0765344513            6   \n",
       "175905   278582  0312991460            6   \n",
       "176255   278582  0425193772            5   \n",
       "175763   278582  0312990456            5   \n",
       "175506   278582  0312983298            3   \n",
       "174867   278582  0061063746            2   \n",
       "176571   278582  076534503X            0   \n",
       "176389   278582  048627263X            0   \n",
       "176565   278582  0743497988            0   \n",
       "176486   278582  0553574027            0   \n",
       "176579   278582  1555971792            0   \n",
       "176385   278582  0451208498            0   \n",
       "176524   278582  0743448677            0   \n",
       "14574    278582  0312966970            0   \n",
       "176331   278582  0451205146            0   \n",
       "17190    278582  0553581112            0   \n",
       "175758   278582  0312985649            0   \n",
       "175103   278582  0312976275            0   \n",
       "174902   278582  0312971346            0   \n",
       "174891   278582  0312851561            0   \n",
       "174890   278582  0312168586            0   \n",
       "174869   278582  0140250360            0   \n",
       "174852   278582  0061032484            0   \n",
       "174815   278582  0060549270            0   \n",
       "174814   278582  0060534397            0   \n",
       "174809   278582  0060534389            0   \n",
       "116741   278582  0380817152            0   \n",
       "46554    278582  0312966091            0   \n",
       "24674    278582  0425175405            0   \n",
       "175760   278582  0312986327            0   \n",
       "\n",
       "                                               Book-Title  \n",
       "174885         Chinese Bell Murders (Judge Dee Mysteries)  \n",
       "176582                               Skin Deep, Blood Red  \n",
       "40008    The Left Hand of Darkness (Remembering Tomorrow)  \n",
       "174861                                 Search the Shadows  \n",
       "58156                     The Songcatcher: A Ballad Novel  \n",
       "64570   The No. 1 Ladies' Detective Agency (Today Show...  \n",
       "175958                                The Mists of Avalon  \n",
       "176314  Murdering Mr. Monti: A Merry Little Tale of Se...  \n",
       "174877                                  Blanche Cleans Up  \n",
       "176438                 The Cat Who Brought Down the House  \n",
       "176503  Cetaganda (Bujold, Lois Mcmaster. Vorkosigan A...  \n",
       "176484                            Service of All the Dead  \n",
       "176187  Imitation in Death (Eve Dallas Mysteries (Pape...  \n",
       "175949                               From Doon With Death  \n",
       "176263  Brunswick Gardens (Charlotte &amp; Thomas Pitt...  \n",
       "176290              One Fine Day the Rabbi Bought a Cross  \n",
       "176305                                Incident at Badamya  \n",
       "174882                                  Blanche Passes Go  \n",
       "176584     Daddy's Gone A-Hunting (Wesley Farrell Novels)  \n",
       "176572                            The Jewel That Was Ours  \n",
       "23996                                   I Is for Innocent  \n",
       "60802                                   Two for the Dough  \n",
       "108791                                Death of a Stranger  \n",
       "176517                          Maggody and the Moonbeams  \n",
       "174895                                    The Venus Throw  \n",
       "175303                  Seven Up (A Stephanie Plum Novel)  \n",
       "175596  Hard Eight : A Stephanie Plum Novel (A Stephan...  \n",
       "176171                                      The Wife Test  \n",
       "176139                                   Holiday in Death  \n",
       "176562                              CSI, Miami: Heat Wave  \n",
       "176567  Over the Wine-Dark Sea (Hellenistic Seafaring ...  \n",
       "175905              To the Nines (A Stephanie Plum Novel)  \n",
       "176255                                       Indigo Dying  \n",
       "175763         One for the Money (A Stephanie Plum Novel)  \n",
       "175506         Full Speed (Janet Evanovich's Full Series)  \n",
       "174867                                         Hang Loose  \n",
       "176571  The Gryphon's Skull (Hellenistic Seafaring Adv...  \n",
       "176389  Flatland: A Romance of Many Dimensions (Dover ...  \n",
       "176565  Law and Order Deadline : An Original Law and O...  \n",
       "176486                                         Antarctica  \n",
       "176579                             The Body in Four Parts  \n",
       "176385                                  Thieves' Paradise  \n",
       "176524   Without Pity : Ann Rule's Most Dangerous Killers  \n",
       "14574              Four To Score (A Stephanie Plum Novel)  \n",
       "176331                     Black Hawk Down (Movie Tie-in)  \n",
       "17190   Justice Hall: A Mary Russell Novel (Mary Russe...  \n",
       "175758               A Grave Denied (A Kate Shugak Novel)  \n",
       "175103  Hot Six : A Stephanie Plum Novel (A Stephanie ...  \n",
       "174902                 High Five (A Stephanie Plum Novel)  \n",
       "174891             The Sword of Samurai Cat (Tor Fantasy)  \n",
       "174890                                        Great Harry  \n",
       "174869                   Blanche Among the Talented Tenth  \n",
       "174852                              Children of the Storm  \n",
       "174815     A Greek God at the Ladies' Club (Avon Romance)  \n",
       "174814                                  All Shall Be Well  \n",
       "174809                                   A Share in Death  \n",
       "116741               The Golden One : A Novel of Suspense  \n",
       "46554   Three To Get Deadly : A Stephanie Plum Novel (...  \n",
       "24674                                        Black Notice  \n",
       "175760            Out on a Limb (A Claire Malloy Mystery)  "
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "book_rating.loc[book_rating['User-ID'] == 278582].sort_values(by=['Book-Rating'], ascending=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
